 #ifndef __SELECT_SEVER_HPP__
 #define __SELECT_SEVER_HPP__


#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include"Sock.hpp"
#include"Log.hpp"

#define BITS 8
#define NUM (sizeof(fd_set)*BITS)
#define FD_NONE -1

using namespace std;

class SelectServer
{
public:
    SelectServer(const uint16_t &port = 8080)
        : _port(port)
    {
        _listensock = Sock::Socket();
        Sock::Bind(_listensock, 8080);
        Sock::Listen(_listensock);
        for (int i = 0; i < NUM; i++) 
        {
            _fd_array[i] = FD_NONE;
        }
        _fd_array[0] = _listensock;

    }

    void Start()
    {
        while(true)
        {
            fd_set rfds;
            FD_ZERO(&rfds);
            int maxfd = _listensock;

            for (int i = 0; i < NUM; i++)
            {
                if(_fd_array[i] == FD_NONE) continue;
                FD_SET(_fd_array[i], &rfds);
                if(maxfd < _fd_array[i])
                    maxfd = _fd_array[i];
            }
            int n = select(maxfd + 1, &rfds, nullptr, nullptr, nullptr);
            switch (n)
            {
            case 0:
                logMessage(DEBUG, "time out...");
                break;
            case -1:
                logMessage(DEBUG, "select error!");
                break;
            default:
                //成功
                logMessage(DEBUG, "select success");
                HandlerEvent(rfds);
                break;
            }
        }
        
    }
private:

    void HandlerEvent(const fd_set &rfds)
    {
        //先找到就绪的fd，判断是读取事件还是链接事件
        for (int i = 0; i < NUM; i++ )
        {
            if(_fd_array[i] == FD_NONE) continue;
            if(FD_ISSET(_fd_array[i], &rfds))
            {
                if(_fd_array[i] == _listensock)
                    Accepter();
                else Recver(i);
            }
        }
    }

    void Accepter()
    {
        std::string clientip;
        uint16_t clientport = 0;

        int sock = Sock::Accept(_listensock, &clientip, &clientport);
        if(sock < 0)
        {
            logMessage(ERROR, "accept error!");
            return;
        }

        //把accept获取的sock添加到数组中
        int pos = 0;
        for (; pos < NUM; pos++ ) 
        {
            if(_fd_array[NUM] != FD_NONE)
                break;
        }
        if(pos == NUM)
        {
            logMessage(WARNING, "%s:%d", "select server already full,close: %d", sock);
            close(sock);
        }
        else
            _fd_array[pos] = sock;
    }

    void Recver(int pos)
    {
        char buffer[1024];
        memset(&buffer, 0, sizeof(buffer));

        int n = recv(_fd_array[pos], buffer, sizeof buffer - 1, 0);
        
        if(n > 0)
        {

            buffer[n] = 0;
            printf("%s", buffer);
            logMessage(DEBUG, "client[%d]# %s", _fd_array[pos], buffer);
        }
        else if(n == 0)
        {
            logMessage(DEBUG, "client[%d]quit, me too... ", _fd_array[pos]);
            //1.关闭不需要的文件描述符
            close(_fd_array[pos]);
            //2.让select不再关注这个sock
            _fd_array[pos] = FD_NONE;
        }
        else//n < 0
        {
            logMessage(WARNING, "sock recv error!%d",_fd_array[pos]);
            //1.关闭不需要的文件描述符
            close(_fd_array[pos]);
            //2.让select不再关注这个sock
            _fd_array[pos] = FD_NONE;
        }
    }


    uint16_t _port;
    int _listensock;
    int _fd_array[NUM];

};





 #endif